package com.ibeeking.found.open.b.rest.service.impl;


import com.ibeeking.found.common.constants.WxCpServiceTypeConstant;
import com.ibeeking.found.common.entity.open.*;
import com.ibeeking.found.common.enums.OpenApiConfigEnum;
import com.ibeeking.found.common.enums.WxCpAppTypeEnum;
import com.ibeeking.found.common.response.ResponseCodeEnum;
import com.ibeeking.found.common.utils.DataUtils;
import com.ibeeking.found.common.utils.UrlUtils;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.gmc.global.api.feign.GlobalOpenFeignClient;
import com.ibeeking.found.open.api.common.param.cop.CopDepartmentParam;
import com.ibeeking.found.open.api.common.param.OpenAuthParam;
import com.ibeeking.found.open.api.feign.CopFeignClient;
import com.ibeeking.found.open.api.feign.OpenFileFeignClient;
import com.ibeeking.found.open.api.feign.GlobalOpenAuthFeignClient;
import com.ibeeking.found.open.b.rest.config.prop.RedisProperties;
import com.ibeeking.found.open.b.rest.service.IOpenService;
import com.ibeeking.found.open.b.rest.service.IWxCpContactEventService;
import com.ibeeking.found.open.service.common.constants.RedisKeyConstant;
import com.ibeeking.found.open.service.common.param.QueryOpenAuthInfoParam;
import com.ibeeking.found.open.service.common.vo.OpenAuthVO;
import com.ibeeking.found.open.service.common.vo.OpenAuthViewVO;
import com.ibeeking.found.open.service.common.vo.UrlVO;
import com.ibeeking.found.open.service.config.OpenAuthCallBackConfig;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.file.oss.dto.OssPolicyDto;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.redis.utils.RedisUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.file.FileUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseResult;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.error.WxRuntimeException;
import me.chanjar.weixin.common.redis.JedisWxRedisOps;
import me.chanjar.weixin.cp.bean.WxCpTpDepart;
import me.chanjar.weixin.cp.bean.WxCpTpPermanentCodeInfo;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.bean.message.WxCpTpXmlMessage;
import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
import me.chanjar.weixin.cp.config.impl.WxCpTpDefaultConfigImpl;
import me.chanjar.weixin.cp.config.impl.WxCpTpRedissonConfigImpl;
import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
import me.chanjar.weixin.cp.constant.WxCpTpConsts;
import me.chanjar.weixin.cp.message.WxCpMessageRouter;
import me.chanjar.weixin.cp.tp.service.WxCpTpDepartmentService;
import me.chanjar.weixin.cp.tp.service.WxCpTpService;
import me.chanjar.weixin.cp.tp.service.WxCpTpUserService;
import me.chanjar.weixin.cp.tp.service.impl.WxCpTpServiceImpl;
import me.chanjar.weixin.cp.util.crypto.WxCpTpCryptUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @ClassName WxCpTpEventServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-06-18 12:21
 **/
@Service("wxCpContactEventServiceImpl")
@EnableConfigurationProperties({RedisProperties.class})
public class WxCpContactEventServiceImpl implements IWxCpContactEventService {
    private static final Logger log = LoggerFactory.getLogger(WxCpContactEventServiceImpl.class);

    private static final Long EXPIRE_TIME = 7000L; // 100分钟

    private static final Map<String, WxCpMessageRouter> wxCpMessageRouterMap = new Hashtable();

    @Resource
    private RedisUtils redisUtils;

    @Autowired
    private RedisProperties redisProperties;

    @Resource
    private OpenFileFeignClient openFileFeignClient;

    @Resource
    private CopFeignClient copFeignClient;

    @Resource
    private IOpenService openServiceImpl;

    @Resource
    private GlobalOpenAuthFeignClient globalOpenAuthFeignClient;

    @Resource
    private GlobalOpenFeignClient globalOpenFeignClient;

    @Resource
    private OpenAuthCallBackConfig openAuthCallBackConfig;

    @Override
    public String authWxCpContactTicket(HttpServletRequest request, HttpServletResponse response, String signature, String timestamp, String nonce, String echostr) {
        try {
            OpenConfigDTO wxOpenConfigDTO = queryWxOpenConfigByType(OpenApiConfigEnum.OPEN_CONFIG_TYPE_WECHAT_CP.getCode(), WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_CONTACT.getCode());
            if (null == wxOpenConfigDTO) {
                throw new BusinessException("无法获取开发平台参数信息");
            }
            WxCpTpService wxCpContactService = openServiceImpl.getDefaultWxCpContactService();
            if (wxCpContactService == null)  throw new BusinessException("获取企微服务失败!");
            WxCpTpConfigStorage wxCpTpConfigStorage = wxCpContactService.getWxCpTpConfigStorage();

            WxCpTpCryptUtil cryptUtil = new WxCpTpCryptUtil(wxCpTpConfigStorage);
            String encryptedXml = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
            String inMessage = cryptUtil.decryptXml(signature, timestamp, nonce, encryptedXml);
            if(inMessage == null) return "success";

            LogUtils.info("auth:消息解密后内容为：\n{} ", JsonUtils.toJsonStr(inMessage));

            WxCpTpXmlMessage wxCpTpXmlMessage = WxCpTpXmlMessage.fromXml(inMessage);
            Map<String, Object> jsonObject = wxCpTpXmlMessage.getAllFieldsMap();
            String out = null;
            if(WxCpTpConsts.InfoType.SUITE_TICKET.equals(wxCpTpXmlMessage.getInfoType())) {
                String suitId = wxCpTpXmlMessage.getSuiteId();
                String suiteTicket = wxCpTpXmlMessage.getSuiteTicket();
                Integer timeStamp = Integer.getInteger(wxCpTpXmlMessage.getTimeStamp());
                LogUtils.info("\nSUITE_TICKET：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));

                wxCpTpConfigStorage.updateSuiteTicket(suiteTicket, 20*60);
                redisUtils.set(RedisKeyConstant.WX_CP_CONTACT_SUITE_TICKET + suitId,suiteTicket,20*60);
                checkAndUpdateSuiteToken(wxCpContactService, suitId);
                checkAndUpdateAuthorizeAccessToken(wxCpContactService, suitId);
            }
            return "success";
        }catch(Exception ex){
            return "success";
        }

    }

    @Override
    public Object msgWxCpContactEvent(HttpServletRequest request, HttpServletResponse response, String signature, String timestamp, String nonce, String echostr) {
       try {
           WxCpTpService wxCpTpService = openServiceImpl.getDefaultWxCpDkService();
           if (wxCpTpService == null) {
               throw new BusinessException("获取企微服务失败!");
           }
           WxCpTpConfigStorage wxCpTpConfigStorage = wxCpTpService.getWxCpTpConfigStorage();
           WxCpTpCryptUtil cryptUtil = new WxCpTpCryptUtil(wxCpTpConfigStorage);

           String inMessage = cryptUtil.decryptXml(signature, timestamp, nonce, IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8));
           if(inMessage == null) return "success";

           LogUtils.info("msgCpDkEvent:消息解密后内容为：\n{} ", JsonUtils.toJsonStr(inMessage));

           WxCpTpXmlMessage wxCpTpXmlMessage = WxCpTpXmlMessage.fromXml(inMessage);
           String out = "success";

           return out;
       }catch(Exception ex){
           return "";
       }

    }

    /**
     * 通讯录授权
     *
     * @param contactSecret
     * @return
     * @throws Exception
     * @Author ibeeking
     */
    @Override
    public Boolean authWxCpDkContactList(String corpAppId, String contactSecret)  {
        LogUtils.info("contact_Access param corpId：{}; contactSecret:{} ", corpAppId, contactSecret);
        String tenantId = UserUtils.getTenantId();
        if(StringUtils.isEmpty(tenantId)){
            DataUtils.trueThrowException(true, "获取租户tenantId失败:" + tenantId);
        }
        OpenConfigDTO wxOpenConfigDTO = queryWxOpenConfigByType(OpenApiConfigEnum.OPEN_CONFIG_TYPE_WECHAT_CP.getCode(),WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_DK.getCode());

        OpenAuthDTO wxOpenAuthDTO = queryWxOpenAuthByType(Long.valueOf(tenantId), WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_DK.getCode());
        if (null == wxOpenAuthDTO) throw new BusinessException("读取配置信息失败！");
        OpenAuthOfExtend openAuthOfExtend = wxOpenAuthDTO.getOpenAuthOfExtend();
        OpenAuthOfWxCpDk openAuthOfWxCpDk = openAuthOfExtend.getOpenAuthOfWxCpDk();
        String openAppId = wxOpenAuthDTO.getOpenAppId();
        String suiteId = wxOpenAuthDTO.getComponentAppId();

        WxCpTpService wxCpTpService = openServiceImpl.getDefaultWxCpDkService();
        if(null == wxCpTpService) throw new BusinessException("企业微信服务初始化还未完成，请稍候再试");
        WxCpTpConfigStorage wxCpTpConfigStorage = wxCpTpService.getWxCpTpConfigStorage();
        wxCpTpService.setWxCpTpConfigStorage(wxCpTpConfigStorage);

        if(StringUtils.isNotEmpty(contactSecret)){
            WxAccessToken contactWxAccessToken = getContactAccessToken(wxCpTpService, corpAppId, contactSecret);
            if (contactWxAccessToken != null) {
                String contactAccessToken = contactWxAccessToken.getAccessToken();
                wxCpTpConfigStorage.updateAccessToken(corpAppId, contactAccessToken, contactWxAccessToken.getExpiresIn());
                redisUtils.set(RedisKeyConstant.WX_CP_DK_CORP_ACCESS + suiteId, contactAccessToken, EXPIRE_TIME);
                LogUtils.info("\n auth WxCpDk contact_Access：\n{} ", contactAccessToken);

                OpenAuthParam openAuthParam = BeanUtil.convertBean(wxOpenAuthDTO, OpenAuthParam.class);
                openAuthParam.setConfigType(OpenApiConfigEnum.OPEN_CONFIG_TYPE_WECHAT_CP.getCode());
                openAuthParam.setConfigSubType(WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_DK.getCode());
                openAuthParam.setAppSecret(contactSecret);

                LogUtils.info("\n update WxCpDk openAuthParam：\n{} ", JsonUtils.toJsonStr(openAuthParam));
                globalOpenAuthFeignClient.modifyAuth(openAuthParam);
            }
            if (contactWxAccessToken != null) {
                //导入通讯录
                try {
                    WxCpTpDepartmentService wxCpTpDepartmentService = wxCpTpService.getWxCpTpDepartmentService();
                    if (wxCpTpDepartmentService == null) throw new BusinessException("获取企微部门服务失败!");
                    String authCorpId = wxOpenAuthDTO.getOpenAppId();
                    Long tenanatId = wxOpenAuthDTO.getTenantId();

                    List<WxCpTpDepart> wxCpTpDeparts = wxCpTpDepartmentService.list(authCorpId);
                    if (Collections3.isNotEmpty(wxCpTpDeparts)) {
                        List<CopDepartmentParam> copDepartmentParams = new ArrayList<>();
                        copDepartmentParams = wxCpTpDeparts.parallelStream().map(d -> {
                            CopDepartmentParam copDepartmentParam = new CopDepartmentParam();
                            copDepartmentParam.setId(d.getId().longValue());
                            copDepartmentParam.setName(d.getName());
                            copDepartmentParam.setNickName(d.getEnName());
                            copDepartmentParam.setTenantId(tenanatId);
                            copDepartmentParam.setParentId(d.getParentid().longValue());
                            copDepartmentParam.setSort(d.getOrder());

                            return copDepartmentParam;
                        }).collect(Collectors.toList());
                        LogUtils.info("\n List<CopDepartmentParam>：\n{} ", JsonUtils.toJsonStr(copDepartmentParams));
                        copFeignClient.batchInsertDepartmentListFromWxCp(copDepartmentParams);
                    }

                    WxCpTpUserService wxCpTpUserService = wxCpTpService.getWxCpTpUserService();
                    if (wxCpTpUserService == null) throw new BusinessException("获取企微员工服务失败!");
                    List<WxCpUser> wxCpUsers = wxCpTpUserService.listByDepartment(1L, false, 0, authCorpId);
                }catch(Exception ex){
                    return false;
                }
            }
        }
        return true;
    }
    /**
     * 授权注册页面扫码授权   显示二维码
     *
     * @param request
     * @return
     * @throws Exception
     * @Author ibeeking
     */
    @Override
    public UrlVO getWxCpContactPreAuthUrl(HttpServletRequest request) throws Exception {
        OpenConfigDTO wxOpenConfigDTO = queryWxOpenConfigByType(OpenApiConfigEnum.OPEN_CONFIG_TYPE_WECHAT_CP.getCode(), WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_CONTACT.getCode());
        DataUtils.trueThrowException(wxOpenConfigDTO == null, "系统异常:微信第三放平台appId为空!");
        String openAppId =  wxOpenConfigDTO.getOpenAppId();
        String suiteId = wxOpenConfigDTO.getComponentAppId();
        String wxOpenCpContactAuthRedirectUrl = openAuthCallBackConfig.getWxOpenCpContactAuthRedirectUrl();
        String tenantId = UserUtils.getTenantId();
        DataUtils.trueThrowException(StringUtils.isBlank(wxOpenCpContactAuthRedirectUrl), "微信第三方授权后的跳转页面尚未配置!");

        WxCpTpService wxCpContactService = openServiceImpl.getDefaultWxCpContactService();
        if(null == wxCpContactService) throw new BusinessException("企业微信服务初始化还未完成，请稍候再试");
        WxCpTpConfigStorage configStorage = wxCpContactService.getWxCpTpConfigStorage();
        LogUtils.info("========WxCpTpConfigStorage：{}========", JsonUtils.toJsonStr(configStorage));
        String suiteTicket = configStorage.getSuiteTicket();
        if(StringUtils.isEmpty(suiteTicket)){
            String suiteTicketredis = redisUtils.getString(RedisKeyConstant.WX_CP_CONTACT_SUITE_TICKET + suiteId);
            if(StringUtils.isNotEmpty(suiteTicketredis)) {
                configStorage.updateSuiteTicket(suiteTicketredis, 1200);
            }
        }
        String suiteAccessToken = configStorage.getSuiteAccessToken();
        if(StringUtils.isEmpty(suiteAccessToken)){
            Object suiteAccessObj = redisUtils.get(RedisKeyConstant.WX_CP_CONTACT_SUITE_ACCESS_TOKEN + suiteId);
            if(ObjectUtils.isNotEmpty(suiteAccessObj)) {
                WxAccessToken oldSuiteAccessTokenEntity = (WxAccessToken)suiteAccessObj;
                configStorage.updateSuiteAccessToken(oldSuiteAccessTokenEntity);
            }
        }
        wxOpenCpContactAuthRedirectUrl = wxOpenCpContactAuthRedirectUrl + "?openAppId=" + openAppId + "&suiteId=" + suiteId + "&type=" + WxCpServiceTypeConstant.CP_TYPE_CONTACT;


        String url = wxCpContactService.getPreAuthUrl(wxOpenCpContactAuthRedirectUrl, tenantId, 1);
        //String result = wxCpTpService.get(url,null);
        LogUtils.info("========CallBack result：{}========", JsonUtils.toJsonStr(url));
        return new UrlVO().setUrl(url);
    }

    /**
     * 获取永久授权码
     *
     * @param queryParam
     * @return
     * @throws Exception
     * @Author ibeeking
     */
    @Override
    public OpenAuthViewVO getWxCpContactPermanentAuthInfo(QueryOpenAuthInfoParam queryParam) throws Exception {
        LogUtils.info("========queryParam：{}========", JsonUtils.toJsonStr(queryParam));
        if(queryParam == null) throw new BusinessException("无法读取查询参数信息");
        OpenAuthViewVO openAuthViewVO = new OpenAuthViewVO();
        String authCode = queryParam.getAuthCode();
        if(StringUtils.isEmpty(authCode)) throw new BusinessException("获取临时授权码空");

        OssPolicyDto  ossPolicyDto = getOssFilePolicy();
        String tenantId = queryParam.getTenantId();
        String state = queryParam.getState();
        String suiteId = queryParam.getComponentAppId();
        String preAuthCodeExpiredIn = queryParam.getExpiresIn();

        OpenAuthParam param = new OpenAuthParam();
        OpenAuthOfExtend openAuthOfExtend = new OpenAuthOfExtend();
        if(StringUtils.isEmpty(tenantId)){
            tenantId = state;
        }
        if(StringUtils.isNotEmpty(tenantId)) {
            param.setTenantId(Long.valueOf(tenantId));
        }

        OpenConfigDTO wxOpenConfigDTO = queryWxOpenConfigByType(OpenApiConfigEnum.OPEN_CONFIG_TYPE_WECHAT_CP.getCode(), WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_CONTACT.getCode());

        DataUtils.trueThrowException(wxOpenConfigDTO == null, "系统异常:微信第三放平台appId为空!");

        String openAppId =  wxOpenConfigDTO.getOpenAppId();
        String suiteAppId = wxOpenConfigDTO.getComponentAppId();
        param.setOpenId(wxOpenConfigDTO.getId());
        param.setConfigType(wxOpenConfigDTO.getType());
        param.setConfigSubType(wxOpenConfigDTO.getSubType());
        param.setOpenAppId(openAppId);
        param.setComponentAppId(suiteAppId);
        param.setComponentAppSecret(wxOpenConfigDTO.getComponentSecret());
        param.setAppToken(wxOpenConfigDTO.getComponentMsgToken());
        param.setAppAesKey(wxOpenConfigDTO.getComponentMsgAesKey());
        param.setAppType(WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_CONTACT.getCode());
        WxCpTpService wxCpContactService = openServiceImpl.getDefaultWxCpContactService();
        if(null == wxCpContactService) throw new BusinessException("企业微信服务初始化还未完成，请稍候再试");
        WxCpTpConfigStorage configStorage = wxCpContactService.getWxCpTpConfigStorage();
        String suiteTicket = configStorage.getSuiteTicket();
        if(StringUtils.isEmpty(suiteTicket)){
            String suiteTicketObj = redisUtils.getString(RedisKeyConstant.WX_CP_CONTACT_SUITE_TICKET + suiteAppId);
            if(ObjectUtils.isNotEmpty(suiteTicketObj)) {
                configStorage.updateSuiteTicket(suiteTicketObj, 1200);
            }
        }

        OpenAuthOfWxCpContact openAuthOfWxCpContact = new OpenAuthOfWxCpContact();
        openAuthOfWxCpContact.setSuiteTicket(configStorage.getSuiteTicket());
        openAuthViewVO = BeanUtil.convertBean(param, OpenAuthViewVO.class);
        String suiteAccessToken = configStorage.getSuiteAccessToken();
        if(StringUtils.isEmpty(suiteAccessToken)) {
            Object suiteAccessObj = redisUtils.get(RedisKeyConstant.WX_CP_CONTACT_SUITE_ACCESS_TOKEN + suiteAppId);
            if (ObjectUtils.isNotEmpty(suiteAccessObj)) {
                WxAccessToken oldSuiteAccessTokenEntity = (WxAccessToken) suiteAccessObj;
                configStorage.updateSuiteAccessToken(oldSuiteAccessTokenEntity);
            } else {
                WxAccessToken wxAccessToken = wxCpContactService.getSuiteAccessTokenEntity(true);
                openAuthOfWxCpContact.setSuiteAccessToken(wxAccessToken.getAccessToken());
                openAuthOfWxCpContact.setSuiteAccessExpirein(System.currentTimeMillis() + wxAccessToken.getExpiresIn() * 1000);
                redisUtils.set(RedisKeyConstant.WX_CP_CONTACT_SUITE_ACCESS_TOKEN + suiteAppId, wxAccessToken, EXPIRE_TIME.intValue());
            }
        }
        openAuthOfWxCpContact.setSuiteAccessExpireTime(EXPIRE_TIME.intValue());
        openAuthOfWxCpContact.setPreAuthCode(authCode);
        WxCpTpPermanentCodeInfo wxCpTpPermanentCodeInfo = wxCpContactService.getPermanentCodeInfo(authCode);
        LogUtils.info("========wxCpTpPermanentCodeInfo：{}========", JsonUtils.toJsonStr(wxCpTpPermanentCodeInfo));
        String permanentCode  = wxCpTpPermanentCodeInfo.getPermanentCode();
        redisUtils.set(RedisKeyConstant.WX_CP_CONTACT_PERMANENT_CODE + suiteAppId, permanentCode, EXPIRE_TIME);
        openAuthOfWxCpContact.setPermanentCode(permanentCode);
        WxCpTpPermanentCodeInfo.AuthCorpInfo rtnAuthCorpInfo = wxCpTpPermanentCodeInfo.getAuthCorpInfo();
        LogUtils.info("========wxCpTpAuthInfo：{}========", JsonUtils.toJsonStr(rtnAuthCorpInfo));
        //授权企业信息
        if(rtnAuthCorpInfo != null) {
            String authCorpId = rtnAuthCorpInfo.getCorpId();
            OpenAuthOfWxCpTpAuthCorpInfo authCorpInfo = BeanUtil.convertBean(rtnAuthCorpInfo, OpenAuthOfWxCpTpAuthCorpInfo.class);
            authCorpInfo.setCorpid(authCorpId);
            param.setAppId(authCorpId);
            openAuthViewVO.setAppId(authCorpId);
            openAuthViewVO.setName(authCorpInfo.getCorpName());
            if(StringUtils.isNotEmpty(rtnAuthCorpInfo.getCorpRoundLogoUrl())) {
                try {
                    String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(rtnAuthCorpInfo.getCorpId()).concat("_roundLogo.png"));
                    String fileTag = ossPolicyDto.getDir() + fileName;
                    MultipartFile multipartFile = FileUtils.getMultipartFile(rtnAuthCorpInfo.getCorpRoundLogoUrl(), fileName, fileTag);
                    ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
                    String fileUploadPath = responseResult.getData();
                    authCorpInfo.setCorpRoundLogoUrl(UrlUtils.removeUrlDomainName(fileUploadPath));
                } catch (Exception ex) {
                    authCorpInfo.setCorpRoundLogoUrl("");
                }
            }

            if(StringUtils.isNotEmpty(rtnAuthCorpInfo.getCorpSquareLogoUrl())) {
                try {
                    String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(rtnAuthCorpInfo.getCorpId()).concat("_squareLogo.png"));
                    String fileTag = ossPolicyDto.getDir() + fileName;
                    MultipartFile multipartFile = FileUtils.getMultipartFile(rtnAuthCorpInfo.getCorpSquareLogoUrl(), fileName, fileTag);
                    ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
                    String fileUploadPath = responseResult.getData();
                    authCorpInfo.setCorpSquareLogoUrl(UrlUtils.removeUrlDomainName(fileUploadPath));
                } catch (Exception ex) {
                    authCorpInfo.setCorpSquareLogoUrl("");
                }
            }

            if(StringUtils.isNotEmpty(rtnAuthCorpInfo.getCorpWxQrcode())) {
                try {
                    String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(rtnAuthCorpInfo.getCorpId()).concat("_qrcode.png"));
                    String fileTag = ossPolicyDto.getDir() + fileName;
                    MultipartFile multipartFile = FileUtils.getMultipartFile(rtnAuthCorpInfo.getCorpWxQrcode(), fileName, fileTag);
                    ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
                    String fileUploadPath = responseResult.getData();
                    authCorpInfo.setCorpWxqrcode(UrlUtils.removeUrlDomainName(fileUploadPath));
                } catch (Exception ex) {
                    authCorpInfo.setCorpWxqrcode("");
                }
            }
            openAuthOfWxCpContact.setAuthCorpInfo(authCorpInfo);
            WxAccessToken wxAccessToken = wxCpContactService.getCorpToken(authCorpId,permanentCode, true);
            if(wxAccessToken != null ){
                String corpAccessToken = wxAccessToken.getAccessToken();
                if(StringUtils.isNotEmpty(corpAccessToken)){
                    openAuthOfWxCpContact.setCorpAccessToken(corpAccessToken);
                    openAuthOfWxCpContact.setCorpAccessExpirein(System.currentTimeMillis() + wxAccessToken.getExpiresIn() * 1000);
                    redisUtils.set(RedisKeyConstant.WX_CP_CONTACT_CORP_ACCESS.concat(suiteAppId).concat(":").concat(authCorpId), wxAccessToken, EXPIRE_TIME.intValue());
                }
            }
        }

        openAuthOfExtend.setOpenAuthOfWxCpContact(openAuthOfWxCpContact);
        param.setOpenAuthOfExtend(openAuthOfExtend);
        LogUtils.info("========param：{}========", JsonUtils.toJsonStr(param));
        globalOpenAuthFeignClient.modifyAuth(param);
        openAuthViewVO.setHasOpenAuth(true);
        return openAuthViewVO;//new UrlVO().setUrl(wxOpenCpTpAuthRedirectUrl);
    }


    @Override
    public OpenAuthVO queryWxCpContactOpenAuthInfo()  {
        Long tenantId = UserUtils.getTenantID();
        if(tenantId == null){
            DataUtils.trueThrowException(true, "获取租户tenantId失败:" + tenantId);
        }

        OpenAuthDTO wxOpenAuthDTO = queryWxOpenAuthByType(tenantId, WxCpServiceTypeConstant.CP_TYPE_CONTACT);
        if (null != wxOpenAuthDTO) {
            OpenAuthVO openAuthVO = BeanUtil.convertBean(wxOpenAuthDTO, OpenAuthVO.class);
            OpenAuthOfExtend openAuthOfExtend = wxOpenAuthDTO.getOpenAuthOfExtend();
            if(openAuthOfExtend!=null) {
                OpenAuthOfWxCpContact openAuthOfWxCpContact = openAuthOfExtend.getOpenAuthOfWxCpContact();
                if(openAuthOfWxCpContact!=null) {
                    OssPolicyDto ossPolicyDto = getOssPolicy();
                    if (null != ossPolicyDto) {
                        OpenAuthOfWxCpTpAuthCorpInfo authCorpInfo = openAuthOfWxCpContact.getAuthCorpInfo();
                        String dnsHost = ossPolicyDto.getHost();
                        if (StringUtils.isNotEmpty(authCorpInfo.getCorpSquareLogoUrl())) {
                            authCorpInfo.setCorpSquareLogoUrl(dnsHost + "/" + authCorpInfo.getCorpSquareLogoUrl());
                        }
                        if (StringUtils.isNotEmpty(authCorpInfo.getCorpWxqrcode())) {
                            authCorpInfo.setCorpWxqrcode(dnsHost + "/" + authCorpInfo.getCorpWxqrcode());
                        }
                    }
                    openAuthVO.setHasOpenAuth(openAuthOfWxCpContact.getCorpAccessToken()!=null);
                }
            }
            openAuthVO.setOpenAuthOfExtend(openAuthOfExtend);
            return openAuthVO;
        } else {
            OpenAuthVO openAuthVO = new OpenAuthVO();
            openAuthVO.setTenantId(tenantId);
            OpenAuthOfExtend openAuthOfExtend = new OpenAuthOfExtend();
            OpenAuthOfWxCpContact openAuthOfWxCpContact = new OpenAuthOfWxCpContact();
            openAuthOfWxCpContact.setAuthCorpInfo(new OpenAuthOfWxCpTpAuthCorpInfo());
            openAuthOfExtend.setOpenAuthOfWxCpContact(openAuthOfWxCpContact);
            openAuthVO.setOpenAuthOfExtend(openAuthOfExtend);
            openAuthVO.setHasOpenAuth(openAuthOfWxCpContact.getCorpAccessToken()!=null);
            return openAuthVO;
        }
    }

    private void checkAndUpdateSuiteToken(WxCpTpService wxCpContactService, String suiteId){
        WxCpTpConfigStorage wxCpContactConfigStorage = wxCpContactService.getWxCpTpConfigStorage();
        Object objSuiteAccessTokenEntity = redisUtils.get(RedisKeyConstant.WX_CP_CONTACT_SUITE_ACCESS_TOKEN + suiteId);
        if(ObjectUtils.isNotEmpty(objSuiteAccessTokenEntity)) {
            WxAccessToken oldSuiteAccessTokenEntity = (WxAccessToken)objSuiteAccessTokenEntity;
            int oldExpiresIn = oldSuiteAccessTokenEntity.getExpiresIn();
            if ((oldExpiresIn - System.currentTimeMillis()) <= 600*1000) {
                try {
                    WxAccessToken newSuiteAccessTokenEntity = wxCpContactService.getSuiteAccessTokenEntity(true);
                    if (newSuiteAccessTokenEntity != null) {
                        wxCpContactConfigStorage.updateSuiteAccessToken(newSuiteAccessTokenEntity);
                        redisUtils.set(RedisKeyConstant.WX_CP_CONTACT_SUITE_ACCESS_TOKEN + suiteId, newSuiteAccessTokenEntity, EXPIRE_TIME);
                    }
                } catch (WxErrorException ex) {
                    throw new BusinessException("获取suiteAccessToken 出错");
                }
            }
        }else{
            try {
                WxAccessToken newSuiteAccessTokenEntity = wxCpContactService.getSuiteAccessTokenEntity(true);
                if (newSuiteAccessTokenEntity != null) {
                    wxCpContactConfigStorage.updateSuiteAccessToken(newSuiteAccessTokenEntity);
                    redisUtils.set(RedisKeyConstant.WX_CP_CONTACT_SUITE_ACCESS_TOKEN + suiteId, newSuiteAccessTokenEntity, EXPIRE_TIME);
                }
            } catch (WxErrorException ex) {
                throw new BusinessException("获取suiteAccessToken 出错");
            }
        }
    }
    /**
     * 跟新授权Token
     *
     * @param suiteId
     * @param wxCpContactService
     */
    private void checkAndUpdateAuthorizeAccessToken(WxCpTpService wxCpContactService, String suiteId) throws Exception{
        List<OpenAuthDTO> wxOpenAuthDTOS = queryWxOpenAuthListByComponentID(suiteId);
        if(Collections3.isNotEmpty(wxOpenAuthDTOS)) {
            wxOpenAuthDTOS.stream().forEach(wxOpenAuthDTO -> {
                try {
                    checkAndUpdateWxCpContactGlobalOpenAuthParam(wxCpContactService, wxOpenAuthDTO);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

    /**
     * 跟新授权Token
     *
     * @param wxCpContactService
     */
    private void checkAndUpdateWxCpContactGlobalOpenAuthParam(WxCpTpService wxCpContactService, OpenAuthDTO wxOpenAuthDTO)  throws Exception{
        //更新global OpenAuth
        if (null != wxOpenAuthDTO) {
            OpenAuthOfExtend openAuthOfExtend = wxOpenAuthDTO.getOpenAuthOfExtend();
            OpenAuthOfWxCpContact openAuthOfWxCpContact = openAuthOfExtend.getOpenAuthOfWxCpContact();
            String permanentCode = openAuthOfWxCpContact.getPermanentCode();
            String appId = wxOpenAuthDTO.getAppId();
            String suiteId = wxOpenAuthDTO.getComponentAppId();

            WxCpTpConfigStorage wxCpContactConfigStorage = wxCpContactService.getWxCpTpConfigStorage();
            String suiteAccessToken = wxCpContactConfigStorage.getSuiteAccessToken();

            String suiteTicket = wxCpContactConfigStorage.getSuiteTicket();

            Object oldCorpAccessTokenObj = redisUtils.get(RedisKeyConstant.WX_CP_CONTACT_CORP_ACCESS.concat(suiteId).concat(":").concat(appId));
            if(ObjectUtils.isNotEmpty(oldCorpAccessTokenObj) ) {
                WxAccessToken oldCorpAccessTokenEntity = (WxAccessToken)oldCorpAccessTokenObj;
                int corpAccessTokenExpiredIn = oldCorpAccessTokenEntity.getExpiresIn();
                if((corpAccessTokenExpiredIn - System.currentTimeMillis()) <= 600 * 1000) {
                    WxAccessToken newCorpAccessTokenEntity = wxCpContactService.getCorpToken(appId, permanentCode, true);
                    if (newCorpAccessTokenEntity != null) {
                        wxCpContactConfigStorage.updateAccessToken(appId, newCorpAccessTokenEntity.getAccessToken(), newCorpAccessTokenEntity.getExpiresIn());
                        redisUtils.set(RedisKeyConstant.WX_CP_CONTACT_CORP_ACCESS + suiteId, newCorpAccessTokenEntity, EXPIRE_TIME);
                    }
                }
            }else{
                WxAccessToken oldCorpAccessTokenEntity = wxCpContactConfigStorage.getAccessTokenEntity(appId);
                redisUtils.set(RedisKeyConstant.WX_CP_CONTACT_CORP_ACCESS + suiteId, oldCorpAccessTokenEntity, EXPIRE_TIME);
            }
            String corpAccessToken = wxCpContactConfigStorage.getAccessToken(appId);
            if (!StringUtils.equalsAnyIgnoreCase(suiteAccessToken, openAuthOfWxCpContact.getSuiteAccessToken()) ||
                    !StringUtils.equalsAnyIgnoreCase(corpAccessToken, openAuthOfWxCpContact.getCorpAccessToken())
            ) {
                //LogUtils.info("\n begin Update WxCpTp OpenAuthParam：\n ");
                OpenAuthParam openAuthParam = BeanUtil.convertBean(wxOpenAuthDTO, OpenAuthParam.class);
                openAuthParam.setConfigType(OpenApiConfigEnum.OPEN_CONFIG_TYPE_WECHAT_CP.getCode());
                openAuthParam.setConfigSubType(WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_CONTACT.getCode());

                if (StringUtils.isNotEmpty(corpAccessToken)) {
                    WxAccessToken corpAccessTokenEntity = wxCpContactConfigStorage.getAccessTokenEntity(appId);
                    openAuthOfWxCpContact.setCorpAccessToken(corpAccessTokenEntity.getAccessToken());
                    openAuthOfWxCpContact.setCorpAccessExpirein(System.currentTimeMillis() + corpAccessTokenEntity.getExpiresIn() * 1000);
                }
                if (StringUtils.isNotEmpty(suiteAccessToken)) {
                    WxAccessToken suiteAccessTokenEntity = wxCpContactConfigStorage.getSuiteAccessTokenEntity();
                    openAuthOfWxCpContact.setSuiteAccessToken(suiteAccessTokenEntity.getAccessToken());
                    openAuthOfWxCpContact.setSuiteAccessExpirein(System.currentTimeMillis() + suiteAccessTokenEntity.getExpiresIn() * 1000);
                }
                if (StringUtils.isNotEmpty(suiteTicket))
                    openAuthOfWxCpContact.setSuiteTicket(suiteTicket);
                LogUtils.info("\n update WxCpTp openAuthParam：\n{} ", JsonUtils.toJsonStr(openAuthParam));
                globalOpenAuthFeignClient.modifyAuth(openAuthParam);
            }
        }
    }

    private OssPolicyDto getOssPolicy() {
        ResponseResult<OssPolicyDto> ossPolicyResult = openFileFeignClient.policy();
        DataUtils.trueThrowException(!ResponseCodeEnum.SUCCESS.getCode().equals(ossPolicyResult.getCode()), ossPolicyResult.getMsg());
        return ossPolicyResult.getData();
    }
    /**
     * @return
     * @Author ibeeking
     * 返回公众号授权信息
     */
    private OpenAuthDTO queryWxOpenAuthByType(Long tenantId, Integer appType) {
        OpenAuthQuery query = new OpenAuthQuery();
        query.setTenantId(tenantId);
        query.setAppType(appType);
        ResponseResult<OpenAuthDTO> responseResult = globalOpenFeignClient.queryOpenAuthOne(query);
        return responseResult.getData();
    }

    private List<OpenAuthDTO> queryWxOpenAuthListByComponentID(String componentAppId) {
        OpenAuthQuery query = new OpenAuthQuery();
        query.setComponentAppId(componentAppId);
        ResponseResult<List<OpenAuthDTO>> responseResult = globalOpenFeignClient.queryOpenAuthList(query);
        return responseResult.getData();
    }

    private OpenAuthDTO queryWxOpenAuthByComponentAppIdAndType(String componentAppId, Integer appType) {
        OpenAuthQuery query = new OpenAuthQuery();
        query.setComponentAppId(componentAppId);
        query.setAppType(appType);
        ResponseResult<OpenAuthDTO> responseResult = globalOpenFeignClient.queryOpenAuthOne(query);
        return responseResult.getData();
    }


    private OpenConfigDTO queryWxOpenConfigByType(Integer type,Integer subType) {
        OpenConfigQuery query = new OpenConfigQuery();
        query.setType(type);
        query.setSubType(subType);
        ResponseResult<OpenConfigDTO> responseResult = globalOpenFeignClient.queryOpenConfigOne(query);
        return responseResult.getData();
    }

    private WxCpTpConfigStorage getWxCpContactRedissonConfigStorage(OpenConfigDTO wxOpenConfigDTO) {
        WxCpTpConfigStorage configStorage = WxCpTpRedissonConfigImpl.builder()
                .keyPrefix("wx:cp:contact")
                .corpId(wxOpenConfigDTO.getOpenAppId())
                .corpSecret(wxOpenConfigDTO.getOpenAppSecret())
                .suiteId(wxOpenConfigDTO.getComponentAppId())
                .suiteSecret(wxOpenConfigDTO.getComponentSecret())
                .token(wxOpenConfigDTO.getComponentMsgToken())
                .aesKey(wxOpenConfigDTO.getComponentMsgAesKey())
                .providerSecret(wxOpenConfigDTO.getOpenAppSecret())
                .wxRedisOps(new JedisWxRedisOps(redisProperties.getJedisPool()))
                .build();
        return configStorage;
    }

    private WxAccessToken getContactAccessToken(WxCpTpService wxCpTpService, String corpId, String corpSecret) {
        try {
            WxCpTpServiceImpl wxCpTpServiceImpl = new WxCpTpServiceImpl();
            WxCpTpDefaultConfigImpl configStorage = new WxCpTpDefaultConfigImpl();
            wxCpTpServiceImpl.setWxCpTpConfigStorage(configStorage);

            String url = String.format(configStorage.getApiUrl(WxCpApiPathConsts.GET_TOKEN), corpId, corpSecret);
            try {
                HttpGet httpGet = new HttpGet(url);
                String resultContent;
                try (CloseableHttpClient httpClient = wxCpTpServiceImpl.getRequestHttpClient();
                    CloseableHttpResponse response = httpClient.execute(httpGet)) {
                    resultContent = new BasicResponseHandler().handleResponse(response);
                } finally {
                    httpGet.releaseConnection();
                }
                WxError error = WxError.fromJson(resultContent, WxType.CP);
                if (error.getErrorCode() != 0) {
                    throw new WxErrorException(error);
                }

                WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
                return accessToken;
            } catch (IOException e) {
                throw new WxRuntimeException(e);
            }
        }catch(WxErrorException ex){
            return null;
        }
    }

    private OssPolicyDto getOssFilePolicy(){
        ResponseResult<OssPolicyDto> responseResult = openFileFeignClient.policy();
        return responseResult.getData();
    }

}
